package com.ericsson.common.util;


import com.alibaba.fastjson.JSON;
import com.ericsson.common.pojo.MyFileLock;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;

import java.io.*;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;


public class FileUtil {

	/**
	 * 创建新文件
	 *
	 * @param parentDirs
	 * @param child
	 * @param override
	 * @return
	 * @throws IOException
	 */
	public static File newFile(File parentDirs, String child, boolean override) throws IOException {

		if (!parentDirs.exists() || !parentDirs.isDirectory()) {
			parentDirs.mkdirs();
		}

		File childFile = new File(parentDirs, child);
		if (!childFile.exists() || !childFile.isFile()) {
			childFile.createNewFile();
		} else if (override) {
			childFile.delete();
			childFile.createNewFile();
		}

		return childFile;
	}

	/**
	 * 创建新文件
	 *
	 * @param parent
	 * @param child
	 * @param override
	 * @return
	 * @throws IOException
	 */
	public static File newFile(String parent, String child, boolean override) throws IOException {

		File parentDirs = new File(parent);

		return newFile(parentDirs, child, override);
	}

	/**
	 * 如果目录不存在则创建目录
	 *
	 * @param dir
	 * @return 目录File
	 */
	public static File newDirs(String dir) {

		File dirFile = new File(dir);

		return newDirs(dirFile);

	}
	/**
	 * 如果目录存在则删除目录
	 *
	 * @param dir
	 * @return 目录File
	 */
	public static boolean deleteDir(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();// 递归删除目录中的子目录下
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
				}
			}
		} // 目录此时为空，可以删除
		return dir.delete();
	}

	/**
	 * 删除目录下的所有文件，保留根目录
	 *
	 * @param dir
	 * @return 目录File
	 */
	public static boolean deleteSubFiles(File dir) {
		if (dir.isDirectory()) {
			String[] children = dir.list();// 递归删除目录中的子目录下
			for (int i = 0; i < children.length; i++) {
				boolean success = deleteDir(new File(dir, children[i]));
				if (!success) {
					return false;
				}
			}
		}
		return true;
	}


	/**
	 * 删除目录下的所有文件
	 *
	 * @param dir
	 */
	public static void deleteWorkDir(File dir) {
		if (dir.exists()) {
			File[] files = dir.listFiles();
			for (File file : files) {
				if (file.exists() && file.canWrite()) {
					file.delete();
				}
			}
		}
	}


	/**
	 * 删除文件
	 *
	 * @param filePath
	 * @return
	 */
	public static boolean deleteFile(String filePath) {
		File tempFile = new File(filePath);
		if (tempFile.exists() && tempFile.isFile()) {
			return tempFile.delete();
		}
		return true;
	}

	/**
	 * 如果目录不存在则创建目录
	 *
	 * @param dirFile
	 * @return 目录File
	 */
	public static File newDirs(File dirFile) {

		if (!dirFile.exists() || !dirFile.isDirectory()) {

			dirFile.mkdirs();

		}

		return dirFile;

	}

	/**
	 * 创建子目录
	 *
	 * @param parent
	 * @param child
	 * @return
	 */
	public static File newDirs(String parent, String child) {

		File parentDirFile = new File(parent);

		if (!parentDirFile.exists() || !parentDirFile.isDirectory()) {
			parentDirFile.mkdirs();
		}

		String subDirStr = parent + File.separatorChar + child;

		File subDirStrFile = new File(subDirStr);

		if (!subDirStrFile.exists() || !subDirStrFile.isDirectory()) {
			subDirStrFile.mkdirs();
		}

		return subDirStrFile;
	}

	/**
	 * 创建子目录
	 *
	 * @param parent
	 * @param child
	 * @return
	 */
	public static File newDirs(File parent, String child) {

		String filePath = parent.getAbsolutePath();

		return newDirs(filePath, child);
	}

	/**
	 * 复制文件
	 *
	 * @param source
	 * @param dest
	 */
	public static void copy(File source, File dest) {

		if (!source.exists()) {

			return;

		} else if (source.isFile()) {

			if (dest.exists() && dest.isFile()) {
				dest.delete();
			}

			try {
				dest.createNewFile();
			} catch (IOException ex) {
				ex.printStackTrace();
			}

		}

		FileInputStream fis = null;
		BufferedInputStream bis = null;

		FileOutputStream fos = null;
		BufferedOutputStream bos = null;

		byte[] bytes = new byte[1024 * 5];

		try {

			fis = new FileInputStream(source);
			bis = new BufferedInputStream(fis);

			fos = new FileOutputStream(dest);
			bos = new BufferedOutputStream(fos);

			int count = -1;
			while ((count = bis.read(bytes)) > 0)  {
				bos.write(bytes, 0, count);
			}

		} catch (IOException ex) {

			return;

		} finally {

			try {

				fis.close();
				bis.close();
				bos.close();
				fos.close();

			} catch (IOException ex) {

			}
		}
	}

	/**
	 * 获取文件数字字符串
	 *
	 * @param fileName
	 * @return
	 */
	public static String getCDRFileNameNumber(String fileName) {

		String fileNameWS = getCDRFileNameWithoutSuffix(fileName);

		String fileType = getCDRType(fileName);

		return fileNameWS.substring(fileType.length(), fileNameWS.length());
	}

	/**
	 * 根据给出的话单文件路径获取不含.suffix的文件名称字符串
	 *
	 * @param filePath
	 * @return
	 */
	public static String getCDRFileNameWithoutSuffixFromPath(String filePath) {

		String fileNameWithSuffix = getCDRFileNameFromPath(filePath);

		String fileNameWithoutSuffix = getCDRFileNameWithoutSuffix(fileNameWithSuffix);

		return fileNameWithoutSuffix;
	}

	/**
	 * 通过文件路径（相对或绝对）获取文件名称
	 *
	 * @param filePath 文件路径
	 * @return
	 */
	public static String getCDRFileNameFromPath(String filePath) {

		String fileSeperator = File.separator;

		int lastSeperatorIndex = filePath.lastIndexOf(fileSeperator);

		if (lastSeperatorIndex < 0) {
			return filePath;
		}

		String fileName = filePath.substring(lastSeperatorIndex + 1, filePath.length());

		return fileName;
	}

	/**
	 * 通过话单文件名获取不含.suffix的文件名称字符串
	 *
	 * @param filename
	 * @return
	 */
	public static String getCDRFileNameWithoutSuffix(String filename) {

		int dotIndex = filename.indexOf('.');

		if (dotIndex < 0) {
			return filename;
		}

		return filename.substring(0, dotIndex);
	}

	/**
	 * 获取话单类型字符串
	 *
	 * @param filename
	 * @return
	 */
	public static String getCDRType(String filename) {

		int dateStartIndex = dateSerialStartIndex(filename);

		return filename.substring(0, dateStartIndex);
	}

	/**
	 * 通过文件路径获取话单类型字符串
	 *
	 * @param filePath
	 * @return
	 */
	public static String getCDRTypeFromPath(String filePath) {

		String fileName = getCDRFileNameFromPath(filePath);

		int dateStartIndex = dateSerialStartIndex(fileName);

		return fileName.substring(0, dateStartIndex);
	}

	/**
	 * 获取日期字符串
	 *
	 * @param filename
	 * @return
	 */
	public static String getCDRDatetime(String filename) {

		int dateStartIndex = dateSerialStartIndex(filename);

		return filename.substring(dateStartIndex, dateStartIndex + 14);
	}

	/**
	 *
	 *
	 * @param filename
	 * @return
	 */
	public static String getCDRDate(String filename) {

		int dateStartIndex = dateSerialStartIndex(filename);

		return filename.substring(dateStartIndex, dateStartIndex + 8);
	}

	/**
	 * 获取话单文件的四位序列号
	 *
	 * @param filename
	 * @return
	 */
	public static String getCDRSerialNum(String filename) {

		int dateStartIndex = dateSerialStartIndex(filename);

		return filename.substring(dateStartIndex + 14, dateStartIndex + 18);
	}

	/**
	 * 通过不含.suffix的文件名称字符串获取日期字符串的开始索引
	 *
	 * @param filename
	 * @return
	 */
	private static int dateSerialStartIndex(String filename) {

		int dotIndex = filename.indexOf('.');

		return dotIndex - 18;
	}

	/**
	 * 获取文件行记录数量
	 *
	 * @param file
	 * @return
	 * @throws Exception
	 */
	public static long getLineCount(File file) throws Exception {

		LineNumberReader lnr = new LineNumberReader(new FileReader(file));

		lnr.skip(Long.MAX_VALUE);

		long count = lnr.getLineNumber();

		lnr.close();

		return count;
	}

	/**
	 * 独占方式拷贝文件
	 *
	 * @param src
	 * @param dest
	 */
	public static void syncCopyFile(File src, final File dest) {

		new MyFileLock(src) {

			@Override
			protected void doFile() throws Exception {

				final FileChannel oldFileChannel = this.fileChannel;

				new MyFileLock(dest) {

					@Override
					protected void doFile() throws Exception {

						this.fileChannel.transferFrom(oldFileChannel, 0, oldFileChannel.size());

					}

				}.run();
			}

		}.run();
	}

	/**
	 * 独占方式剪切文件
	 *
	 * @param src
	 * @param dest
	 */
	public static void syncMoveFile(File src, final File dest) {

		new MyFileLock(src) {

			@Override
			protected void doFile() throws Exception {

				final FileChannel oldFileChannel = this.fileChannel;

				new MyFileLock(dest) {

					@Override
					protected void doFile() throws Exception {

						this.fileChannel.transferFrom(oldFileChannel, 0, oldFileChannel.size());

					}

				}.run();
			}

		}.run();

		src.delete();
	}


	/**
	 * 将in文件内容append到out文件中
	 * @param in
	 * @param out
	 * @throws IOException
	 */
	public static void fileCopy( File in, File out ) throws IOException {
	    FileChannel inChannel = new FileInputStream(in).getChannel();
	    FileChannel outChannel = new FileOutputStream(out,true).getChannel();

	    try {
	        inChannel.transferTo(0, inChannel.size(), outChannel);
	     } finally {
	         if (inChannel != null) {
	             inChannel.close();
	         }
	         if (outChannel != null) {
	             outChannel.close();
	         }
	     }
	 }

	public static List<String> func(File file,List<String> list){
		File[] fs = file.listFiles();
		for(File f:fs){
			if(f.isDirectory())	//若是目录，则递归打印该目录下的文件
				func(f,list);
			if(f.isFile())		//若是文件，直接打印
				//System.out.println(f.getAbsolutePath());
				list.add(f.getAbsolutePath());
		}
		return list;
	}

	public static void fileMv(String srcFile,String dest) throws IOException, InterruptedException{
		//System.out.println("mv "+ srcFile + " " + dest);
		Process	proc = Runtime.getRuntime().exec("mv "+ srcFile + " " + dest);
		proc.waitFor();
		proc.destroy();
	}

	/**
	 * 删除目录及目录下的文件
	 *
	 * @param dir：要删除的目录的文件路径
	 * @return 目录删除成功返回true，否则返回false
	 */
	public static boolean deleteDirectory(String dir) {
		// 如果dir不以文件分隔符结尾，自动添加文件分隔符
		if (!dir.endsWith(File.separator))
			dir = dir + File.separator;
		File dirFile = new File(dir);
		// 如果dir对应的文件不存在，或者不是一个目录，则退出
		if ((!dirFile.exists()) || (!dirFile.isDirectory())) {
			System.out.println("删除目录失败：" + dir + "不存在！");
			return false;
		}
		boolean flag = true;
		// 删除文件夹中的所有文件包括子目录
		File[] files = dirFile.listFiles();
		for (int i = 0; i < files.length; i++) {
			// 删除子文件
			if (files[i].isFile()) {
				flag = deleteFile(files[i].getAbsolutePath());
				if (!flag)
					break;
			}
			// 删除子目录
			else if (files[i].isDirectory()) {
				flag = deleteDirectory(files[i].getAbsolutePath());
				if (!flag)
					break;
			}
		}
		if (!flag) {
			System.out.println("删除目录失败！");
			return false;
		}
		// 删除当前目录
		if (dirFile.delete()) {
			System.out.println("删除目录" + dir + "成功！");
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 写入文件
	 */
	public static void writeToFile(String fileName, String content, boolean append) {
		try {
			FileUtils.write(new File(fileName), content, "utf-8", append);
			System.out.println("文件 " + fileName + " 写入成功!");
		} catch (IOException e) {
			System.out.println("文件 " + fileName + " 写入失败! " + e.getMessage());
		}
	}

	public static void writeToFile(List<Object> content, File file) {
		FileWriter fw = null;
		PrintWriter pw = null;
		try {
			if (file.exists()) {
				fw = new FileWriter(file, true);
				pw = new PrintWriter(fw);
				pw.println(JSON.toJSONString(content));
				pw.flush();
				fw.flush();
			}

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			pw.close();
			try {
				fw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 删除过期的目录
	 *
	 * @param descDir 要删除的目录
	 * @param pattern 日期目录的格式
	 * @param days 设定过期目录的天数
	 * @param log 日志记录对象
	 */
	public static void deleteExpireDirs(File descDir, String pattern, int days, Logger log) {

		if (descDir.exists()) {
			Calendar calendar = Calendar.getInstance();
			//设置需删除的日期标志
			calendar.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR) - days);
			String dayflag = new SimpleDateFormat(pattern).format(calendar.getTime());
			File[] dateDirs = descDir.listFiles();
			if (dateDirs != null) {
				for (File dateDir : dateDirs) {
					if (dateDir.isDirectory() && dateDir.getName().compareTo(dayflag) <= 0) {
						FileUtil.deleteDir(dateDir);
						if (log != null) {
							log.info("delete Expire dir :" + dateDir);
						}
					}
				}
			}
		}
	}


}
